#include "pthread.h"
#include <stdio.h>

#include "pub.h"
#include <core_api.h>

typedef struct _bestTimer {
    CORE_TIMER_MODULE_TYPE eModuleType;
    CORE_TIMER_TYPE        eTimerType;
    BEST_UINT32            shouldDelayCircle;
    BEST_UINT32            curDelayCircle;
    BEST_BOOL              enable;
    CORE_TimerCallbackFunc fn;
    BEST_VOID *            para1;
    BEST_VOID *            para2;
    BEST_VOID *            para3;
    BEST_VOID *            para4;
} BestTimer;

BestTimer g_BestTimerTbl[CORE_SPEC_MAX_TIMER_SIZE] = {0};

typedef struct _timerThread {
    BEST_UINT32 baseID;
    BEST_UINT32 workID;
    BEST_BOOL   baseEnable;
    BEST_BOOL   workEnable;
} BestTimerThread;

BestTimerThread g_BestTimerThread = {0};

BEST_UINT64 g_uiTimerBaseCnt = 0;

#define BASE_TIMER_TICK_INTERVAL 1

BEST_VOID CORE_TimerBaseTickRun()
{
    while (1) {
        g_uiTimerBaseCnt++;
        // printf("run base tick func\n");
        sleep(BASE_TIMER_TICK_INTERVAL);
    }
}

BEST_VOID CORE_TimerWorkTickRun()
{
    BEST_UINT32 i;
    while (1) {
        for (i = 0; i < CORE_SPEC_MAX_TIMER_SIZE; i++) {
            BestTimer *tmr = &g_BestTimerTbl[i];
            if (!tmr->enable) {
                continue;
            }
            tmr->curDelayCircle++;
            if (tmr->curDelayCircle >= tmr->shouldDelayCircle) {
                tmr->fn(tmr->para1, tmr->para2, tmr->para3, tmr->para4);
                tmr->curDelayCircle = 0;
            }
        }
        sleep(BASE_TIMER_TICK_INTERVAL);
    }
}

BEST_STATUS CORE_TimerBaseThreadCreate()
{
    if (g_BestTimerThread.baseEnable) {
        return BEST_OK;
    }
    BEST_STATUS uiRet =
        CORE_ThreadCreate(CORE_TimerBaseTickRun, &g_BestTimerThread.baseID);
    if (uiRet != BEST_OK) {
        printf("err\n");
        return BEST_ERR;
    }
    g_BestTimerThread.baseEnable = BEST_TRUE;
    return BEST_OK;
}

BEST_STATUS CORE_TimerWorkThreadCreate()
{
    if (g_BestTimerThread.workEnable) {
        return BEST_OK;
    }
    BEST_STATUS uiRet =
        CORE_ThreadCreate(CORE_TimerWorkTickRun, &g_BestTimerThread.workID);
    if (uiRet != BEST_OK) {
        printf("err\n");
        return BEST_ERR;
    }
    g_BestTimerThread.workEnable = BEST_TRUE;
    return BEST_OK;
}

BEST_STATUS CORE_TimerStart(CORE_TIMER_MODULE_TYPE eModuleType,
                            BEST_UINT32 delay, CORE_TIMER_TYPE eTimerType,
                            CORE_TimerCallbackFunc fn, BEST_VOID *para1,
                            BEST_VOID *para2, BEST_VOID *para3,
                            BEST_VOID *para4)
{
    if (eModuleType >= CORE_SPEC_MAX_TIMER_SIZE) {
        return BEST_ERR;
    }
    if (eTimerType >= E_CORE_TIMER_INVALID) {
        return BEST_ERR;
    }
    if (delay == 0) {
        return BEST_ERR;
    }
    if (fn == NULL) {
        return BEST_ERR;
    }
    BestTimer *tmr = &g_BestTimerTbl[eModuleType];
    if (tmr->enable) {
        printf("current timer have work, duplicate!\n");
        return BEST_OK;
    }
    tmr->enable            = BEST_TRUE;
    tmr->shouldDelayCircle = (BEST_UINT32)(delay / BASE_TIMER_TICK_INTERVAL);
    tmr->curDelayCircle    = 0;
    tmr->eTimerType        = eTimerType;
    tmr->eModuleType       = eModuleType;
    tmr->fn                = fn;
    tmr->para1             = para1;
    tmr->para2             = para2;
    tmr->para3             = para3;
    tmr->para4             = para4;
    printf("reg func of timer, moduleType %d, timerType %d\n", eModuleType,
           eTimerType);
    return BEST_OK;
}

BEST_STATUS CORE_TimerStop(CORE_TIMER_MODULE_TYPE eModuleType)
{
    if (eModuleType >= CORE_SPEC_MAX_TIMER_SIZE) {
        return BEST_ERR;
    }
    BestTimer *tmr = &g_BestTimerTbl[eModuleType];
    if (!tmr->enable) {
        printf("current timer not work!\n");
        return BEST_OK;
    }
    tmr->enable            = BEST_FALSE;
    tmr->shouldDelayCircle = 0;
    tmr->curDelayCircle    = 0;
    tmr->eTimerType        = E_CORE_TIMER_INVALID;
    tmr->eModuleType       = E_CORE_TIMER_MODULE_INVALID;
    tmr->fn                = NULL;
    tmr->para1             = NULL;
    tmr->para2             = NULL;
    tmr->para3             = NULL;
    tmr->para4             = NULL;
    return BEST_OK;
}

BEST_STATUS CORE_TimerInit()
{
    BEST_UINT32 i;
    for (i = 0; i < CORE_SPEC_MAX_TIMER_SIZE; i++) {
        BestTimer *tmr         = &g_BestTimerTbl[i];
        tmr->shouldDelayCircle = 0;
        tmr->curDelayCircle    = 0;
        tmr->eModuleType       = E_CORE_TIMER_MODULE_INVALID;
        tmr->eTimerType        = E_CORE_TIMER_INVALID;
        tmr->fn                = NULL;
        tmr->para1             = NULL;
        tmr->para2             = NULL;
        tmr->para3             = NULL;
        tmr->para4             = NULL;
        tmr->enable            = BEST_FALSE;
    }
    g_BestTimerThread.workEnable = BEST_FALSE;
    g_BestTimerThread.baseEnable = BEST_FALSE;
    if (CORE_TimerBaseThreadCreate() != BEST_OK) {
        return BEST_ERR;
    }
    if (CORE_TimerWorkThreadCreate() != BEST_OK) {
        return BEST_ERR;
    }
    printf("begin create work base thread successfully!\n");
    return BEST_OK;
}
